home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-11-19 | 108.7 KB | 2,596 lines |
- *-----------------------------------------------------------------------
- *-- Program...: DATES.PRG
- *-- Date......: 08/09/1993
- *-- Notes.....: This program is the DATES program for the dUFLP library.
- *-- This version has been through some drastic changes,
- *-- as Jay Parsons overhauled a few routines, and added
- *-- a lot of new ones. See WHATS.NEW and README.TXT
- *-- for details.
- *-----------------------------------------------------------------------
-
- FUNCTION DateText3
- *-----------------------------------------------------------------------
- *-- Programmer..: Miriam Liskin
- *-- Date........: 03/02/1992
- *-- Notes.......: Display date in format Month, year
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 05/21/1991 - original function.
- *-- 03/02/1992 - This one's Douglas P. Saine's (XRED)
- *-- invention. In his words: "I just removed the middle
- *-- part looking for the day. For the things I do, I only
- *-- need the month and year. (I work for a defense
- *-- contractor, accuracy of dates has never been of great
- *-- concern. <G>)"
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: DateText3(<dDate>)
- *-- Example.....: ? DateText3(date())
- *-- Returns.....: July, 1991
- *-- Parameters..: dDate = date to be converted
- *-----------------------------------------------------------------------
-
- parameters dDate
-
- RETURN cmonth(dDate)+", "+str(year(dDate),4)
- *-- EoF: DateText3()
-
- FUNCTION Age2
- *-----------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [HazMatZak] (CIS: 72662,1305)
- *-- Date........: 07/01/1993
- *-- Notes.......: Returns number of full years between two dates, which
- *-- is the age of a person born on the first date as of
- *-- the second.
- *-- Returns 0 if second date is less than a year after
- *-- first date, -1 if second date is before first date by
- *-- one year or less, and so forth. Does not check for
- *-- blank dates.
- *-- Written for.: dBASE IV, 1.1 and above
- *-- Rev. History: 10/23/1991 - Martin Leon ( HMAN ) - original function
- *-- 04/22/1992 - Jay Parsons - description modified and
- *-- parameters changed
- *-- 06/20/1993 - HazMatZak - replaced, better algorithm
- *-- 07/01/1993 - Jay Parsons - changed to use floor()
- *-- instead of int() for coordination with WorkDays()
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Age2(<d1>,<d2>)
- *-- Example.....: ? "A person born "+dtoc( d1 )+" was " ;
- + dtoc( Age2( d1, d2 ) ) +" years old on " ;
- + dtoc( d2 )+"."
- *-- Returns.....: Numeric value in years
- *-- Parameters..: d1 = first date, such as date of birth
- *-- d2 = second date, when age is wanted
- *-----------------------------------------------------------------------
-
- parameters dDate1, dDate2
-
- RETURN floor( ( val( dtos( dDate2 ) ) - val( dtos( dDate1 ) ) ) ;
- / 10000 )
- *-- EoF: Age2()
-
- FUNCTION DoY
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 07/07/1993
- *-- Notes.......: Returns the day of the year of a date (from beginning
- *-- of the year). Known as "Julian" date in government
- *-- and military contexts.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - original function.
- *-- 11/14/1991 - Ken Mayer - expanded for readability ...
- *-- 07/07/1993 - Jay Parsons - revised to use Zak's FDoY()
- *-- Calls.......: FDoY() FUNCTION in Dates.prg
- *-- Called by...: Any
- *-- Usage.......: DoY(<dDate>)
- *-- Example.....: ?DoY({01/01/91})
- *-- Returns.....: Numeric value of day of year
- *-- Parameters..: dDate = Date being tested for ...
- *-----------------------------------------------------------------------
-
- parameters dDate
-
- RETURN dDate - FDoY( dDate ) + 1
- *-- EoF: DoY()
-
- FUNCTION Annivrsry
- *-----------------------------------------------------------------------
- *-- Programmer..: David Love (CIS: 70153,2433) and Jay Parsons
- *-- (CIS: 72662,1302)
- *-- Date........: 11/10/1991
- *-- Notes.......: Checks to see if an anniversary date falls within a
- *-- range of dates (handy for mailings for organizations,
- *-- checking to see if someone's birthday falls within
- *-- certain dates, etc.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - Original Release
- *-- 06/30/1992 - Jay Parsons - revised to work with Zak's
- *-- Age2(), ages less than one year
- *-- Calls.......: Age2() FUNCTION in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Annivrsry(<dTest>,<dBegin>,<dEnd>)
- *-- Example.....: if Annivrsry(dBDay,{03/01/91},{03/31/91})
- *-- *-- do something
- *-- endif
- *-- Returns.....: .T. if a date (dTest), or its anniversary, falls
- *-- within the period beginning at dBegin or ending at
- *-- dEnd, inclusive. Returns .F. for any other
- *-- result, including invalid ranges or blank dates.
- *-- Parameters..: dTest = Date being tested for ...
- *-- dBegin = Beginning of range
- *-- dEnd = End of range
- *-----------------------------------------------------------------------
-
- parameters dTest, dBegin, dEnd
- private nYears
-
- m->nYears = 0
- * This "if" test will fail if a date is blank
- if dBegin <= dEnd .AND. dTest <= dEnd
- m->nYears = age2( dTest, dEnd ) - age2( dTest, dBegin - 1 )
- endif
-
- RETURN m->nYears # 0
- *-- EoF: Annivrsry()
-
- FUNCTION AddMonths
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 06/07/1993
- *-- Notes.......: Finds same day as given date N months ahead.
- *-- This function will return the first day of the
- *-- following month if there is no equal date in the month
- *-- otherwise returned and nMonths is positive, or the
- *-- last day of the month if nMonths is negative. That
- *-- is, a call with {01/31/91} (January 31, 1991) and 1
- *-- would yield March 1, there being no February 31.
- *-- Do not use this function successively to find first
- *-- the date one month ahead, then the date one month
- *-- beyond that. Instead, to find the date two months
- *-- ahead from the original date, call this function with
- *-- the original date and nMonths = 2. Otherwise, in the
- *-- example, you'll get April 1 the second time rather
- *-- than the correct March 31.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 -- Original Release
- *-- 06/07/1993 -- Lee Hite (CIS: 71213,2475). added ROUND
- *-- function in new date computation to prevent decimals
- *-- being returned in the date value. This insures that
- *-- dBase relational operators will work correctly with
- *-- the result, i.e., AddMonths({1/1/91},1)={2/1/91} will
- *-- return true, whereas before it would not, even though
- *-- the calculated date appeared correct when evaluated
- *-- as a character string.
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: AddMonths(<dDate>,<nMonths>)
- *-- Example.....: ?AddMonths({01/01/91},1)
- *-- Returns.....: Date
- *-- Parameters..: dDate = Date being tested for ...
- *-- dMonths = Number of months "ahead"
- *-----------------------------------------------------------------------
-
- parameters dDate, nMonths
- private dNew, dTest,dReturn
-
- m->dNew = dDate - day( dDate )+ 15 ;
- + round( 30.436875 * nMonths, 0 ) &&middle of month
- m->dTest = m->dNew - day( m->dNew ) + day( dDate )
- m->dReturn = iif( month( m->dTest ) = month( m->dNew ), ;
- m->dTest, m->dTest - day( m->dTest ) ;
- + iif( nMonths > 0, 1, 0 ) )
-
- RETURN dReturn
- *-- EoF: AddMonths()
-
- FUNCTION AddYears
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 11/14/1991
- *-- Notes.......: Finds same day as given date N years ahead.
- *-- Using this function dBASE IV will take care of
- *-- converting February 29 to March 1 if moving from a
- *-- leap to a non-leap year. However, it may not be used
- *-- backwards (negative value of nYears) since the date a
- *-- year before February 29, 1992 will be returned as
- *-- March 1, 1991, not February 28, 1991. If you must
- *-- move back, either check explicitly for February 29
- *-- as the original date or add code as in the AddMonths()
- *-- function to test for the date returned being of a
- *-- different month than the original and, if it is, to
- *-- subtract its day().
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - original function.
- *-- 11/14/1991 - Ken Mayer - expanded out to make it
- *-- easier to read, and see what's happening.
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: AddYears(<dDate>,<nYears>)
- *-- Example.....: ?AddYears({01/01/91},1)
- *-- Returns.....: Date
- *-- Parameters..: dDate = Date being tested for ...
- *-- dYears = Number of Years "ahead"
- *-----------------------------------------------------------------------
-
- parameters dDate, nYears
- private cYear,cMonth,cDay,dReturn
-
- m->cYear = str( year( dDate ) + nYears )
- m->cMonth = right( str( month( dDate ) + 100 ), 2 )
- m->cDay = right( str( day( dDate ) + 100 ), 2 )
- m->dReturn = ctod( m->cMonth + "/" + m->cDay + "/" + m->cYear )
-
- RETURN m->dReturn
- *-- EoF: AddYears()
-
- FUNCTION WeekNo
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: Returns the week number of the year of a date (from
- *-- beginning of the year). Week 1 is considered to start
- *-- with the first Sunday of the year. Dates before the
- *-- first Sunday will be returned as week 0 and dates
- *-- on or after the 53rd Sunday as week 53. To change
- *-- this behavior, use max() with 52, or min() with 1, on
- *-- the value returned.
- *-- To use this function but start the week on a different
- *-- day, change the 1 in the second-to-last code line, the
- *-- dow() of Sunday, to the dow() of the day that should
- *-- start each week, 2 for Monday through 7 for Saturday.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - original function.
- *-- 11/14/1991 - Ken Mayer - expanded for readability ...
- *-- 08/02/1993 - Jay Parsons - revised to use FDoY().
- *-- Calls.......: FDoY() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: WeekNo(<dDate>)
- *-- Example.....: ?WeekNo({01/01/91})
- *-- Returns.....: Numeric value of week number
- *-- Parameters..: dDate = Date being tested for ...
- *-----------------------------------------------------------------------
-
- parameters dDate
- private dBaseDate,nReturn
-
- m->dBaseDate = FDoY( dDate ) - 1
- m->dBaseDate = m->dBaseDate - mod( dow( m->dBaseDate - 1 ), 7 )
- * change this value to dow() of day starting week ---^
- m->nReturn = int( ( dDate - m->dBaseDate ) / 7 )
-
- RETURN m->nReturn
- *-- EoF: WeekNo()
-
- FUNCTION EasterDay
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (USSBBS, CIS 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: Returns date of Easter for given year after 1582.
- *-- This gives the date of Easter as celebrated by Western
- *-- churches. The algorithm is from Example 1.3.2.14 of
- *-- Volume I of "The Art of Computer Programming", 2nd
- *-- Edition, Addison-Wesley, Reading, MA, 1973, by Donald
- *-- Knuth, who attributes it to Aloysius Lilius of Naples
- *-- and Christopher Clavius of Germany, both floruit 1582.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/18/1991 - original function.
- *-- 04/22/1992 - Jay Parsons - Notes expanded.
- *-- 11/20/1992 - David Love - Added the private variable
- *-- lYear.
- *-- 12/03/1992 - Jay Parsons - renamed lYear and dPascMoon
- *-- 08/02/1993 - Jay Parsons - changed iif to if/endif
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: EasterDay(<Year>)
- *-- Example.....: EasterDay(91)
- *-- Returns.....: Date (in dBASE date format) of Easter
- *-- Parameters..: nYear = Numeric form of year - YYYY or YY format
- *-----------------------------------------------------------------------
-
- parameters nYear
- private nYr, nGolden, nCentury, nNoLeap
- private nMoonOrbit, nEPact, dPascMoon, dReturn
-
- *-- deal with two digit year ...
- m->nYr = nYear
- if m->nYr < 100
- m->nYr = m->nYr + 100 * int( year( date() ) / 100 )
- endif
-
- m->nGolden = 1 + mod( m->nYr, 19 )
- m->nCentury = floor( m->nYr / 100 ) + 1
- m->nNoLeap = floor( 3 * m->nCentury / 4 ) - 12
- m->nMoonOrbit = floor( ( 8 * m->nCentury + 5 ) / 25 ) - 5
- m->nEPact = mod( 11 * m->nGolden + m->nMoonOrbit - m->nNoLeap ;
- + 20, 30 )
- if m->nEPact = 24 .or. ( m->nEPact = 25 .and. m->nGolden > 11 )
- m->nEpact = m->nEpact + 1
- endif
- m->dPascMoon = ctod( "03/21/" + str( m->nYr ) ) ;
- + mod( 53 - m->nEPact, 30 )
- m->dReturn = m->dPascMoon + 8 - dow( m->dPascMoon )
-
- RETURN m->dReturn
- *-- EoF: EasterDay()
-
- FUNCTION nDoW
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/22/1992
- *-- Notes.......: Numeric Day of Week -- returns the numeric dow value
- *-- of a named day of the week for use by some of the
- *-- other date functions herein.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/25/1992 - original function.
- *-- 04/22/1992 - Jay Parsons - modified example and
- *-- descriptions, added ltrim() of argument.
- *-- Calls.......: None
- *-- Called by...: None
- *-- Usage.......: nDoW(<cDay>)
- *-- Example.....: nDay = nDoW("Tues")
- *-- Returns.....: Numeric dow value of day of week given
- *-- Parameters..: cDay -- Character memvar containing "day" of week
- *-- ('MONDAY', etc ...)
- *-----------------------------------------------------------------------
-
- parameter cDay
-
- RETURN at( upper( left( ltrim( cDay ), 3 ) ), ;
- " SUN MON TUE WED THU FRI SAT" ) / 4
- *-- nDoW()
-
- FUNCTION FWDoM
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 02/25/1992
- *-- Notes.......: First Working Day of the Month -- originally I used
- *-- Dan Madoni's stuff from Technotes, but Jay came along
- *-- and pointed out an easier way to do this. SO, here we
- *-- have a shorter, faster, FWDoM function. This returns
- *-- the date of the first WORKING day ( day that is
- *-- neither Saturday nor Sunday ) of the month of the date
- *-- given as a parameter.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/25/1992 - Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: FWDoM(<dDate>)
- *-- Example.....: ? CDoW( FWDoM(DATE()) ) (character day of week ...)
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-----------------------------------------------------------------------
-
- parameters dDate
- private dReturn, nDay
-
- m->dReturn = dDate - day( dDate ) + 1
- m->nDay = dow( m->dReturn )
-
- RETURN m->dReturn + iif( m->nDay = 7, 2, iif( m->nDay = 1, 1 ,0 ) )
- *-- EoF: FWDoM()
-
- FUNCTION LWDoM
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 02/25/1992
- *-- Notes.......: Last Working Day of the Month -- function from Jay
- *-- (new version like FWDoM) to return the last working
- *-- day of the month. Give a date, the function returns
- *-- the last WORKING day of the month. This has a
- *-- companion function, giving the FIRST working day
- *-- (see above).
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/25/1992 - Original Release
- *-- Calls.......: LDOM() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: LWDoM(<dDate>)
- *-- Example.....: ? LWDoM(DATE())
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-----------------------------------------------------------------------
-
- parameters dDate
- private dReturn, nDay
-
- m->dReturn = LDoM( dDate )
- m->nDay = dow( m->dReturn )
-
- RETURN m->dReturn - iif( m->nDay = 7, 1, iif( m->nDay = 1, 2, 0 ) )
- *-- EoF: LWDoM()
-
- FUNCTION FDoD
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: First Day of Date. This function works to give the
- *-- date of the first occurrence in the month of the given
- *-- date of a given day of the week (i.e., first Monday of
- *-- the month).
- *-- It returns a blank date if the day of week is invalid,
- *-- but is not case sensitive. New, slimmer, sleeker
- *-- version by Jay ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/25/1992 - Original Release
- *-- 08/02/1993 - Jay Parsons - revised to use FDoM().
- *-- Calls.......: NDOW() Function in DATES.PRG
- *-- FDOM() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: FDoD(<dDate>,"<cDay>")
- *-- Example.....: ? FDoD(DATE(),"Tuesday")
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-- cDay -- Day of week to look for ...
- *-----------------------------------------------------------------------
-
- parameters dDate, cDay
- private dReturn, nDay
-
- m->nDay = nDoW(cDay)
- m->dReturn = FDoM( dDate )
-
- RETURN m->dReturn + mod( m->nDay + 7 - dow( dReturn ), 7 )
- *-- EoF: FDoD()
-
- FUNCTION LDoD
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: Last Day of Date. This function works to give the
- *-- date of the last occurrence in the month of the given
- *-- date of a given day of the week (i.e., last Monday of
- *-- the month).
- *-- It returns a blank date if the day of week is invalid,
- *-- but is not case sensitive. New version as FDoD() ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/25/1992 - Original Release
- *-- 08/02/1993 - Jay Parsons - declared nDay private.
- *-- Calls.......: LDOM() Function in DATES.PRG
- *-- NDOW() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: LDoD(<dDate>,"<cDay>")
- *-- Example.....: ? LDoD(DATE(),"Tuesday")
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-- cDay -- Day of week to look for ...
- *-----------------------------------------------------------------------
-
- parameters dDate, cDay
- private dReturn, nDay
-
- m->nDay = nDoW( cDay )
- m->dReturn = LDoM( dDate )
-
- RETURN m->dReturn - mod( dow( m->dReturn ) + 7 - m->nDay, 7 )
- *-- EoF: LDoD()
-
- FUNCTION LDoM
- *-----------------------------------------------------------------------
- *-- Programmer..: Ken Chan [HazMatZak] (CIS: 72662,1305)
- *-- Date........: 02/26/1992
- *-- Notes.......: Last Day of Month -- Zak wrote this one up as a MUCH
- *-- shorter and more straightforward version of one I did.
- *-- >sigh<. This function returns the date of the last
- *- day of the month.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/26/1992 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: LDoM(<dDate>)
- *-- Example.....: ? LDoM(DATE())
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-----------------------------------------------------------------------
-
- parameter dDate
- private dNxtMonth
-
- m->dNxtMonth = dDate - day( dDate ) + 45 && middle of next month
-
- RETURN m->dNxtMonth - day( n->dNxtMonth )
- *-- EoF: LDoM()
-
- FUNCTION NumDoD
- *-----------------------------------------------------------------------
- *-- Programmer..: Ken Mayer (CIS: 71333,1033)
- *-- Date........: 02/24/1992
- *-- Notes.......: This function will return the x daytype of a month.
- *-- Example: what if you need the third Monday of the
- *-- month?
- *- Send to this function a date (any date) of the month,
- *-- the number you need (first, second...) and the day you
- *-- need. The function is not case specific.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/24/1992 -- Original Release
- *-- Calls.......: FDOD() Function in DATES.PRG
- *-- NDOW() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: NumDoD(<dDate>,<nDay>,<cDay>)
- *-- Example.....: ?NumDoD({02/03/92},3,"Monday")
- *-- Returns.....: Date
- *-- Parameters..: dDate = Any date of the month (and year) needed
- *-- nDay = Number of day you need (i.e., third cDay of
- *-- the month
- *-- cDay = Character name of day ("Monday", etc.)
- *-----------------------------------------------------------------------
-
- parameter dDate, nDay, cDay
- private dReturn
-
- m->dReturn = FDoD( dDate, cDay ) && get the first of this dow.
- if nDay > 1 && if a later one is wanted,
- && add 7 days * required # ...
- m->dReturn = m->dReturn + ( ( nDay - 1 ) * 7 )
- endif
-
- RETURN m->dReturn
- *-- EoF: NumDoD()
-
- FUNCTION WDiF
- *-----------------------------------------------------------------------
- *-- Programmer..: Martin Leon (HMAN)
- *-- Date........: 12/12/1991
- *-- Notes.......: This UDF is designed to return the first Working Day
- *-- In the Future of a specific date, based on a # of
- *-- days. For example, to return the first working day, 10
- *-- working days from the current date, you can pass the
- *-- parameters of DATE() and 10. If the date 10 days from
- *-- today is a working day, that date is returned,
- *-- otherwise, the function returns the next succeeding
- *-- working day. You may, if you wish, use a database to
- *-- store holidays. If you do, the database must be laid
- *-- out with the following structure:
- *-- HOLIDAYS.DBF
- *-- Field name Field type MDX?
- *-- HOLIDATE Date Y
- *-- Once the UDF has been run, the database is left open
- *-- in whatever work area it was opened. If another
- *-- database was in use at the time of calling the UDF, it
- *-- becomes the active database after the UDF is done. The
- *-- reason for leaving the database open is that this
- *-- speeds up the process when you call on the UDF several
- *-- times in a row.
- *-- To ensure that holidays are working properly, there
- *-- are 3 assumptions made by this function, and all must
- *-- be true. These are:
- *-- 1) WDIF() assumes that your holidays database
- *-- has an index tag on the HOLIDATE field,
- *-- 2) there are no duplicate entries, and
- *-- 3) none of the holidays in the database falls
- *-- on a weekend date. A simple method for
- *-- insuring the last is:
- *-- USE Holidays
- *-- DELETE ALL FOR dow( Holidate ) = 7 ;
- *-- .or. dow( Holidate ) = 1
- *-- PACK
- *-- If you do not have a Holidays database, this function
- *-- will work fine ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 12/12/1991 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: WDIF(<dStart>,<nDays>)
- *-- Example.....: ?WDiF(date(),10)
- *-- Returns.....: dBASE date
- *-- Parameters..: dStart = Date to start counting from
- *-- nDays = Number of working days in the future ...
- *-----------------------------------------------------------------------
-
- parameter dStart, nWDays
- private nWeeks, nN, nXtraDays, nHDays
- private dReturn, cNear, cAlias, dTemp
-
- store 0 to m->nWeeks, m->nN, m->nHDays, m->nXtraDays
- store {} to m->dReturn, m->dTemp
- store "" to m->cNear, m->cAlias
- m->cNear = set("NEAR")
-
- if nWDays = 0
- RETURN 0
- endif
-
- if type("dStart") + type("nWDays") # "DN"
- RETURN -1
- endif
-
- *-- Rough guestimate of future date within a week
- m->nWeeks = int( nWDays / 5 )
- m->dReturn = dStart + ( m->nWeeks * 7 )
-
- *-- Left over number of days from integer division above
- m->nXtraDays = mod( nWDays, 5 )
-
- *-- Check to see if Holidays database is already in use. This
- *-- is done so that we don't have to close and open the database
- *-- for every call to this UDF. The first call opens it and
- *-- subsequent calls select it as needed.
-
- *-- Check all work areas for holidays database, starting with
- *-- work area 10 since this is most likely where it was opened
- *-- the first time.
- m->nN = 10
- do while .not. "HOLIDAYS" $ alias( m->nN )
- m->nN = m->nN - 1
- if m->nN = 0
- exit
- endif
- enddo
- *-- If it is open, store current alias name and select holidays
- *-- database.
- if m->nN # 0
- m->cAlias = alias()
- select ( alias( m->nN ) )
- else
- *-- If it isn't the currently selected database,
- *-- make sure it exists and use it and select it.
- if file( "HOLIDAYS.DBF" )
- cAlias = alias()
- use Holidays order Holidate in select()
- select Holidays
- endif
- endif
- *-- If it's active now ...
- if alias() = "HOLIDAYS"
- *-- make sure it's in Holidate order, and ...
- if order() # "HOLIDATE"
- set order to Holidate
- endif
- set near on
- *-- count all records in holiday database that fall within
- *-- the range of the starting date and the rough guestimate
- *-- date.
- seek dStart
- *-- don't count starting day if it's in Holidays database.
- if dStart = Holidate
- skip
- endif
- scan while m->dReturn >= Holidate
- m->nHDays = m->nHDays + 1
- endscan
- set near off
- endif
-
- *-- Add holidays to "left over" days from original guestimate
- m->nXtraDays = m->nXtraDays + m->nHDays
-
- *-- Add extra days one day at a time to the guestimate,
- *-- skipping over holidays and weekends.
-
- do while m->nXtraDays > 0
- m->dReturn = m->dReturn + 1
- if alias() = "HOLIDAYS"
- if seek( m->dReturn )
- loop
- endif
- endif
- if dow( m->dReturn ) = 7 .or. dow( m->dReturn ) = 1
- loop
- endif
- m->nXtraDays = m->nXtraDays - 1
- enddo
-
- *-- If return date falls on Saturday or Sunday, "re-wind" to
- *-- Friday.
- m->dReturn = m->dReturn - iif( dow( m->dReturn ) = 7, 1, ;
- iif( dow( m->dReturn) = 1, 2, 0 ) )
-
- *-- If another database was origally in use, make it the active
- *-- database again.
- if "" # m->cAlias
- select ( m->cAlias )
- endif
- *-- set NEAR back to what it was orginally.
- set near &cNear.
-
- RETURN m->dReturn
- *-- EoF: WDiF()
-
- FUNCTION StoD
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: Convert string YYYYMMDD or YYMMDD to a date regardless
- *-- of SET DATE.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - Original Release
- *-- 08/02/1993 - Jay Parsons - cS added to eliminate
- *-- changes to parameter
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: StoD("<cString>")
- *-- Example.....: ?StoD("19910101")
- *-- Returns.....: Date
- *-- Parameters..: <cString> = Date string you wish converted to "normal"
- *-- dBASE date. Must be in either YYYYMMDD or
- *-- YYMMDD format.
- *-----------------------------------------------------------------------
-
- parameters cString
- private dTest, cS, cMonth, cDay, cYear, dReturn
-
- m->dTest = ctod( "01/02/03" )
- m->cS = cString
- if len( m->cS ) < 8
- m->cS = left( str( year( date() ), 4 ), 2 ) + m->cS
- endif
- m->cYear = left( m->cS, 4)
- m->cMonth = substr( m->cS, 5, 2)
- m->cDay = right( m->cS, 2)
- do case
- case month( m->dTest ) = 1
- m->dReturn = ctod( m->cMonth + "/" + m->cDay ;
- + "/" + m->cYear )
- case day( m->dTest ) = 1
- m->dReturn = ctod( m->cDay + "/" + m->cMonth ;
- + "/" + m->cYear )
- otherwise
- m->dReturn = ctod( m->cYear + "/" + m->cMonth ;
- + "/" + m->cDay )
- endcase
-
- RETURN m->dReturn
- *-- EoF: StoD()
-
- FUNCTION Quarter
- *-----------------------------------------------------------------------
- *-- Programmer..: Bowen Moursund (CIS: 72662,436)
- *-- Date........: 02/03/1992
- *-- Notes.......: Returns the quarter of the year of a specific date ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/03/1992 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Quarter(<dDate>)
- *-- Example.....: ?Quarter({05/25/1992})
- *-- Returns.....: Numeric (integer) value from 1 to 4 (or 0 on error )
- *-- Parameters..: dDate = date to be checked
- *-----------------------------------------------------------------------
-
- parameter dDate
-
- RETURN iif(type("dDate")="D",ceiling(month(dDate)/3),0)
- *-- EoF: Quarter()
-
- FUNCTION Dat2Jul
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/01/1992
- *-- Notes.......: Converts dBASE date to Julian # of days (from January
- *-- 1, 4713 B.C.) This is the value of the float dBASE
- *-- uses to store dates, and is used by astronomers. Do
- *-- not use for dBASE dates before 1582, or without con-
- *-- sidering time zones if using for astronomy.
- *-- Rev. History: 03/01/1992 -- Original Release
- *-- Written for.: dBASE IV
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Dat2Jul("<dDate>")
- *-- Example.....: ?Dat2Jul(date())
- *-- Returns.....: Numeric
- *-- Parameters..: dDate = Date to convert to Julian ...
- *-----------------------------------------------------------------------
-
- parameters dDate
-
- RETURN 2415386 + dDate - ctod( "01/01/01" )
- *-- EoF: Dat2Jul()
-
- FUNCTION Jul2Dat
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/01/1992
- *-- Notes.......: Converts Julian # of days to dBASE Date
- *-- Rev. History: 03/01/1992 -- Original Release
- *-- Written for.: dBASE IV
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Jul2Dat(nJulian)
- *-- Example.....: ?Jul2Dat(2448691)
- *-- Returns.....: Date
- *-- Parameters..: nJulian = Julian date to convert to dBase Date
- *-----------------------------------------------------------------------
-
- parameters nJulian
-
- RETURN ctod( "01/01/01" ) + (nJulian - 2415386)
- *-- EoF: Jul2Dat()
-
- FUNCTION FrstNxtMth
- *-----------------------------------------------------------------------
- *-- Programmer..: Todd Barry (TODDBARRY)
- *-- Date........: 08/02/1993
- *-- Notes.......: Returns first day of next month
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 04/04/1992 - Original Release
- *-- 02/25/1993 - Jay Parsons - shortened
- *-- 08/02/1993 - Jay Parsons - conformed to use FDoM().
- *-- Calls.......: FDoM Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: FrstNxtMth(<dDate>)
- *-- Example.....: FrstNxtMth( dDate )
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-----------------------------------------------------------------------
-
- parameters dDate
-
- RETURN FDoM( dDate - day( dDate ) + 45 )
- *-- EoF: FrstNxtMth()
-
- FUNCTION FDoM
- *-----------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 72662,1305)
- *-- Date........: 01/05/1993
- *-- Notes.......: First Day of Month
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: 01/05/1993 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: FDoM(<dArg>)
- *-- Example.....: ?FDOM(date())
- *-- Returns.....: Date
- *-- Parameters..: dArg = a Date argument -- function returns first day
- *-- of the month of this date.
- *-----------------------------------------------------------------------
-
- parameter dArg
-
- RETURN dArg - day( dArg ) + 1
- *-- EoF: FDoM()
-
- FUNCTION FDoY
- *-----------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 72662,1305)
- *-- Date........: 01/05/1993
- *-- Notes.......: Returns January 1 of the year of the date argument
- *-- passed to it.
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: 01/05/1993 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: FDoY(<dArg>))
- *-- Example.....: FDoY(DATE())
- *-- Returns.....: January 1 of the year in dArg
- *-- Parameters..: dArg = date data
- *-----------------------------------------------------------------------
-
- parameter dArg
- private dJan
-
- m->dJan = m->dArg - day( m->dArg ) + 1 - 28 * ( month( m->dArg ) - 1)
-
- RETURN m->dJan - day( m->dJan ) + 1
- *-- EoF: FDoY()
-
- FUNCTION LDoY
- *-----------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 72662,1305)
- *-- Date........: 01/05/1993
- *-- Notes.......: Returns December 31 of year in date argument passed to
- *-- function.
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: 01/05/1993 -- Original Release
- *-- Calls.......: LDoM() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: LDoY(<dArg>)
- *-- Example.....: ?LDoY(Date())
- *-- Returns.....: Last Day of Year
- *-- Parameters..: dArg = Date
- *-----------------------------------------------------------------------
-
- parameter dArg
- private dDec
-
- m->dDec = m->dArg - day( m->dArg ) + 28 * ( 13 - month( m->dArg ))
-
- RETURN LDoM( m->dDec )
- *-- EoF: LDoY()
-
- FUNCTION QDate
- *-----------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [Zak] (CIS:72662,1305)
- *-- Date........: 01/05/1993
- *-- Notes.......: Quicken-style dates
- *-- Works best when BELL is OFF and CONFIRM is ON
- *-- Works with any SET DATE format
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: 01/05/1993 1.0
- *-- Calls.......: FDoM() Function in DATES.PRG
- *-- LDoM() Function in DATES.PRG
- *-- FDoY() Function in DATES.PRG
- *-- LDoY() Function in DATES.PRG
- *-- Strip() Function in STRINGS.PRG
- *-- Called by...: WHEN clause of GET
- *-- Usage.......: @ ... GET <dArg> ... WHEN QDate( <dArg> ) ....
- *--
- *-- Key Function
- *-- --- --------
- *-- T Today's date
- *-- - or _ Day before
- *-- + or = Day after
- *-- M First day of month | Repeated press
- *-- H Last day of month | will give you
- *-- Y First day of year | previous/next
- *-- R Last day of year | month/year
- *-- digit Begin manual date entry
- *--
- *-- Example.....: dFoo = date()
- *-- @ 10,10 get dFoo when QDate( dFoo )
- *-- Returns.....: .T.
- *-- Parameters..: dArg = Date variable/field you're GETting
- *-----------------------------------------------------------------------
-
- parameter dArg
- private lLoop, nRow, nCol, lConfirmOn, nKey, cLastKey, cSimKey,sQdate
-
- m->lLoop = .t.
- m->nRow = row()
- m->nCol = col()
- m->lConfirmOn = ( set( "CONFIRM" ) = "ON" )
- m->cLastKey = ""
- m->cSimKey = ""
-
- *-- Save screen in case of Esc
- save screen to sQDate
-
- *-- Check for skip flag (used when SET CONFIRM is ON)
- if type( "x__QDate" ) # "U"
- release x__QDate
-
- else
- do while m->lLoop
- *-- Display current date in special color
- @ nRow, nCol say m->dArg color gb+/n && <-- use your own color
- *-- Move cursor to beginning of date
- @ nRow, nCol say ""
- *-- Wait for a keypress
- m->nKey = inkey( 0 )
- *-- Convert to uppercase; ignore keys with negative INKEY() values
- m->cKey = upper( chr( max( m->nKey, 0 )))
-
- do case
- case m->cKey = "T" && Today
- m->dArg = date()
- case m->cKey = "-" .or. m->cKey = "_" && The day before
- m->dArg = m->dArg - 1
- case m->cKey = "+" .or. m->cKey = "=" && The day after
- m->dArg = m->dArg + 1
- case m->cKey = "M" && First day of the month
- m->dArg = FDoM( iif( m->cLastKey = "M", m->dArg - 1,;
- m->dArg))
- case m->cKey = "H" && Last day of the month
- m->dArg = LDoM( iif( m->cLastKey = "H", m->dArg + 1,;
- m->dArg))
- case m->cKey = "Y" && First day of the year
- m->dArg = FDoY( iif( m->cLastKey = "Y", m->dArg - 1,;
- m->dArg))
- case m->cKey = "R" && Last day of the year
- m->dArg = LDoY( iif( m->cLastKey = "R", m->dArg + 1,;
- m->dArg))
- case m->cKey $ "0123456789" && Digit -- manual date entry
- m->lLoop = .f.
- *-- Clear entry and start at beginning
- keyboard chr( 25 ) + chr( 26 ) + m->cKey
- case ( m->nKey >= 32 .and. m->nKey < 127 ) .or. m->nKey > 127
- *-- Ignore invalid keys, like letters and symbols
- case m->nKey = 27 .or. m->nKey = 17 && Esc or Ctrl-Q
- m->lLoop = .f.
- *-- Restore screen and quit
- restore screen from sQDate
- keyboard m->cKey
- otherwise
- m->lLoop = .f.
- *-- Figure out how to simulate last keypress
- *-- If SET CONFIRM is OFF
- if .not. m->lConfirmOn
- *-- Go back up to date field
- m->cSimKey = "{UP}" && Up arrow
- *-- Create flag variable to skip routine
- public x__QDate
- endif
- m->cSimKey = m->cSimKey + "{HOME}"
- *-- Recreate keypress
- do case
- case m->nKey = -400
- m->cSimKey = m->cSimKey + "{BACKTAB}"
- otherwise
- m->cSimKey = m->cSimKey + m->cKey
- endcase
- *-- Clear entry and "type in" date without separators
- *-- And simulate last keypress
- keyboard "{HOME}{CTRL-Y}" + Strip( dtoc( m->dArg ), ;
- left( ltrim( dtoc( {} ) ), 1 ) ) + m->cSimKey
- endcase
- *-- Save key just pressed
- m->cLastKey = m->cKey
-
- enddo
-
- endif
-
- *-- release the screen from memory before returning
- release screen sQDate
-
- RETURN .t.
- *-- EoF: QDate()
-
- *-----------------------------------------------------------------------
- *-- For more details on the Hebrew Date routines, see the file included
- *-- called SHANA.TXT, written by Jay Parsons to help explain things.
- *-----------------------------------------------------------------------
-
- FUNCTION Hebrewdate
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (Compuserve 72662,1302)
- *-- Date........: 07/03/1993
- *-- Notes.......: Converts a date to corresponding date on the Hebrew
- *-- calendar. The date returned is the Hebrew date that
- *-- matches the daylight hours of the given civil date;
- *-- the Hebrew date actually starts the evening before.
- *-- Of this family of functions, this is the only
- *-- one containing the names of the months, to simplify
- *-- changing the spelling of any of them. The ruler may
- *-- have to be adjusted if the names are changed, as all
- *-- names must be the same length including padding.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/27/1993 - Jay Parsons - original function
- *-- 07/03/1993 - Jay Parsons - nMolen variable added to
- *-- simplify changing names of months
- *-- 08/03/1993 - Jay Parsons - revised to conform to
- *-- changes to Dat2Heb() in specification of months.
- *-- Calls.......: Dat2Heb() Function in DATES.PRG
- *-- IsLeapH() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Hebrewdate( <dDate> )
- *-- Example.....: ? Hebrewdate( {03/27/93} )
- *-- Returns.....: a character string giving the month, day and year of
- *-- the date, such as "Nisan 5, 5753"
- *-- Parameters..: dDate = a dBASE date
- *-----------------------------------------------------------------------
-
- parameters dDate
- private cDate, cMonths, nMo, cMo, nDay, cDay, nYear, nMolen, nM1
-
- * ruler -> 012345678901234567890123456789012345678901
- m->cMonths = "Tishri HeshvanKislev Tebeth Shebat Adar " + ;
- "Nisan Iyar Sivan Tammuz Ab Ellul "
- m->cDate = Dat2Heb( dDate )
- m->nYear = val( right( m->cDate, 4 ) )
- m->nMo = val( left( m->cDate, 2 ) )
- m->nDay = val( substr( m->cDate, 4, 2 ) )
- m->nMolen = len( m->cMonths ) / 12
- m->nM1 = m->nMo + iif( m->nMo = 0, 6, 0 ) - 1
- m->cMo = trim( substr( m->cMonths, m->nMolen * m->nM1 + 1, ;
- m->nMolen ) ) ;
- + " " + ltrim( str( m->nDay, 2 ) ) + ", " ;
- + right( m->cDate, 4 )
- do case
- case m->nMo = 0
- m->cMo = "First "+ m->cMo
- case m->nMo = 6 .and. isLeapH( m->nYear )
- m->cMo = "Second " + m->cMo
- endcase
-
- RETURN m->cMo
- *-- EoF: HebrewDate()
-
- FUNCTION Civildate
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (Compuserve 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: Converts a Hebrew calendar date to corresponding date
- *-- on the civil calendar. The date returned is the civil
- *-- date that matches the daylight hours of the given
- *-- Hebrew date; the Hebrew day actually starts the
- *-- evening before.
- *-- Supplying the function with a nonexistent 30th
- *-- day of Heshvan or Kishlev is fairly harmless; it will
- *-- return the civil date of the first of the following
- *-- month, the correct date to celebrate a birthday
- *-- falling on the date that does not exist in the given
- *-- year. This is **NOT** sufficient to avoid problems
- *-- with Adar, or with Yahrzeit for deaths occurring on
- *-- Heshvan 30 or Kishlev 30; users are cautioned against
- *-- finding anniversaries in those cases by supplying the
- *-- Hebrew month and date of the event and a different
- *-- Hebrew year as parameters to this function.
- *-- In general, reconverting the civil date
- *-- returned to a Hebrew date and comparing it to the
- *-- original Hebrew date furnished to this function will
- *-- disclose any possible problems, as the two Hebrew
- *-- dates will not match.
- *-- THIS VERSION OF THE FUNCTION IS INCOMPATIBLE
- *-- WITH PREVIOUS ONES--IT INTERPRETS THE PARAMETER
- *-- DIFFERENTLY.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/27/1993 - Original Version.
- *-- 08/02/1993 - Jay Parsons - nX and nY made private,
- *-- method of specifying months changed, error returns
- *-- added.
- *-- Calls.......: Kebiah() Function in DATES.PRG
- *-- Roshashana() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Civildate(<cDate> )
- *-- Example.....: ? Civildate( "05/07/5753" )
- *-- Returns.....: dBase date, the corresponding civil date, or {} if the
- *-- argument fails to specify an existing Hebrew date.
- *-- Parameters..: cDate = character string holding month, day and
- *-- year of Hebrew date, MM/DD/YYYY. Month
- *-- must be in range 00-12. Months 01-12
- *-- correspond to month order in a common
- *-- year, whether or not the year is common
- *-- or a leap year, so that "12" means Ellul
- *-- in any year. "00" means a date in First
- *-- Adar and is meaningless in a common year.
- *-----------------------------------------------------------------------
-
- parameters cDate
- private nMo, nDay, nYear, dDate, cKebiah, aDays, nX, nY, dRet
-
- * blank date for error returns
- m->dRet = {}
- m->nYear = val( right( m->cDate, 4 ) )
- if m->nYear < 1
- RETURN dRet
- endif
- m->nMo = val( left( m->cDate, 2 ) )
- if m->nMo < 0 .or. m->nMo > 12
- RETURN dRet
- endif
- m->nDay = val( substr( m->cDate, 4, 2 ) )
- if m->nDay < 1 .or. m->nDay > 30
- RETURN dRet
- endif
- * find the last day of the Hebrew year preceding this one
- m->dDate = Roshashana( m->nYear ) - 1
- * also Rosh Hashanah of this year and its Kebiah
- m->cKebiah = Kebiah( m->dDate + 1, Roshashana( m->nYear + 1 ) )
- * set up array of the days in the months, using Kebiah to find
- * number of days in Heshvan and Kislev, months 2 and 3. This
- * array is not really required to add the days of each month
- * before the needed one to a running total, but it aids
- * understanding.
- declare aDays[ 13 ]
- aDays[ 1 ] = 30
- aDays[ 2 ] = iif( m->cKebiah $ "EFGLMN", 30, 29 )
- aDays[ 3 ] = iif( m->cKebiah $ "ABHIJ", 29, 30 )
- aDays[ 4 ] = 29
- aDays[ 5 ] = 30
- * in leap years, add days of two Adars, change specification of
- * First Adar to month 6 and add one to later months, converting
- * to their actual positions in the leap year. Otherwise, add
- * 29 days of Adar.
- if m->cKebiah > "G"
- aDays[ 6 ] = 30
- aDays[ 7 ] = 29
- m->nX = 7
- do case
- case m->nMo = 0
- m->nMo = 6
- case m->nMo > 5
- m->nMo = m->nMo + 1
- endcase
- else
- if m->nMo = 0
- RETURN dRet
- endif
- aDays[ 6 ] = 29
- m->nX = 6
- endif
- * for the remaining months, alternate 29 and 30 days
- m->nY = 1
- do while m->nY < 7
- aDays[ m->nX + m->nY ] = 29 + mod( m->nY, 2 )
- m->nY = m->nY + 1
- enddo
- * add up the days in months gone by
- m->nX = 1
- do while m->nX < m->nMo
- m->dDate = m->dDate + aDays[ m->nX ]
- m->nX = m->nX + 1
- enddo
- * and the specified days in this month, if they exist
- if m->nDay <= aDays[ m->nMo ]
- m->dRet = m->dDate + m->nDay
- endif
-
- RETURN m->dRet
- *-- EoF: Civildate()
-
- FUNCTION Dat2Heb
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (Compuserve 72662,1302)
- *-- Date........: 08/03/1993
- *-- Notes.......: Converts a date to corresponding date on the Hebrew
- *-- calendar. The date returned is the Hebrew date that
- *-- matches the daylight hours of the given civil date;
- *-- the Hebrew date actually starts the evening before.
- *-- Do not use this to convert dates before 1582 C.E.,
- *-- because the dBASE specification of such dates is
- *-- erroneous.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/27/1993 - Original version.
- *-- 08/03/1993 - Jay Parsons - conformed to change in
- *-- method of specifying months
- *-- Calls.......: Kebiah() Function in DATES.PRG
- *-- Roshashana() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Dat2Heb( <dDate> )
- *-- Example.....: ? Dat2Heb( {03/27/93} )
- *-- Returns.....: a character string giving the month, day and year of
- *-- the date in numerals, such as "07/05/5753". The month
- *-- will be given as the number of that month in a common
- *-- year, whether or not the year is a leap year, so that
- *-- "07" always means Nisan. A date in First Adar in a
- *-- leap year will be returned as month "00".
- *-- Parameters..: dDate = a dBASE civil date to convert
- *-----------------------------------------------------------------------
-
- parameters dDate
- private nYear, dFirst, dSecond, cKebiah, aDays, nX, nY, nDay, cD
-
- * convert the year to Hebrew year that begins in the civil year
- m->nYear = year( m->dDate ) + 3761
- * find Rosh Hashanah in the year
- m->dFirst = Roshashana( m->nYear )
- * back up if date is in the preceding Hebrew year
- if m->dFirst > m->dDate
- m->nYear = m->nYear - 1
- m->dSecond = m->dFirst
- m->dFirst = Roshashana( m->nYear )
- else
- m->dSecond = Roshashana( m->nYear + 1 )
- endif
- m->cD = "/" + str( m->nYear, 4 )
- * find number of the day within the Hebrew year, and the Kebiah
- m->nDay = 1 + m->dDate - m->dFirst
- m->cKebiah = Kebiah( m->dFirst, m->dSecond )
- * set up array of the days in the months, using Kebiah to find
- * number of days in Heshvan and Kislev, months 2 and 3. This
- * array is not really required to add the days of each month
- * to a running total, but it aids understanding.
- declare aDays[ 13 ]
- aDays[ 1 ] = 30
- aDays[ 2 ] = iif( m->cKebiah $ "EFGLMN", 30, 29 )
- aDays[ 3 ] = iif( m->cKebiah $ "ABHIJ", 29, 30 )
- aDays[ 4 ] = 29
- aDays[ 5 ] = 30
- * in leap years, add days of two Adars, change specification of
- * First Adar to month 6 and add one to later months, converting
- * to their actual positions in the leap year. Otherwise, add
- * 29 days of Adar.
- if m->cKebiah > "G"
- aDays[ 6 ] = 30
- aDays[ 7 ] = 29
- m->nX = 7
- else
- aDays[ 6 ] = 29
- m->nX = 6
- endif
- * for the remaining months, alternate 29 and 30 days
- m->nY = 1
- do while m->nY < 7
- aDays[ m->nX + m->nY ] = 29 + mod( m->nY, 2 )
- m->nY = m->nY + 1
- enddo
- * reduce the day of the year by the days in months past
- m->nX = 1
- do while m->nDay > aDays[ m->nX ]
- m->nDay = m->nDay - aDays[ m->nX ]
- m->nX = m->nX + 1
- enddo
- * adjust month representation in leap years
- if m->cKebiah > "G" .and. m->nX > 5
- m->nX = iif( m->nX = 6, 0, m->nX - 1 )
- endif
- m->cD = transform( m->nX, "@L 99" ) + "/" ;
- + transform( m->nDay, "@L 99" ) + m->cD
-
- RETURN m->cD
- *-- EoF: Dat2Heb()
-
- FUNCTION Kebiah
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (Compuserve 72662,1302)
- *-- Date........: 03/26/1993
- *-- Notes.......: Kebiah of a year, using Arthur Spier's notation.
- *-- This tells whether the year in the Hebrew
- *-- calendar is defective, regular or excessive and
- *-- whether or not a leap year. In order to limit the
- *-- recalculations of Rosh Hashanah in date conversions
- *-- that would be needed if this function were called with
- *-- the year only, it requires the civil dates of the two
- *-- Rosh Hashanahs at start and end as parameters.
- *-- Error checking is limited to determining whether
- *-- the days of the week of the two dates given and number
- *-- of days between them are possible; no check is made
- *-- that either is the correct date of Rosh Hashanah.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/26/1993 -- Original
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Kebiah(<dRosh1>,dRosh2>)
- *-- Example.....: c = Kebiah( {09/16/1993},{09/06/1994} )
- *-- Returns.....: a letter from A through N, signifying as follows:
- *-- A - G common year of 12 months
- *-- H - N leap year of 13 months
- *-- First day of length and type First day
- *-- Letter Rosh Hashanah of year of Passover
- *-- A Monday 353 days, defective Tuesday
- *-- B Sabbath 353 days, defective Sunday
- *-- C Tuesday 354 days, regular Thursday
- *-- D Thursday 354 days, regular Sabbath
- *-- E Monday 355 days, excessive Thursday
- *-- F Thursday 355 days, excessive Sunday
- *-- G Sabbath 355 days, excessive Tuesday
- *-- H Monday 383 days, defective Thursday
- *-- I Thursday 383 days, defective Sunday
- *-- J Sabbath 383 days, defective Tuesday
- *-- K Tuesday 384 days, regular Sabbath
- *-- L Monday 385 days, excessive Sabbath
- *-- M Thursday 385 days, excessive Tuesday
- *-- N Sabbath 385 days, excessive Thursday
- *-- or "" signifying error in dates passed to function.
- *-- Parameters..: dRosh1 = civil date of Rosh Hashanah that starts
- *-- the year
- *-- dRosh2 = civil date of Rosh Hashanah starting the
- *-- following year
- *-----------------------------------------------------------------------
-
- parameters dRosh1, dRosh2
- private dR1, dR2, nDays, nDow, cRet
-
- m->dR1 = min( m->dRosh1, m->dRosh2 )
- m->dR2 = max( m->dRosh1, m->dRosh2 )
- m->nDays = m->dR2 - m->dR1
- m->nDow = dow( m->dR2 )
- * Rosh Hashanah cannot be on Sunday, Wednesday or Friday
- if m->nDow = 1 .or. m->nDow = 4 .or. m->nDow = 6
- RETURN ""
- endif
- m->cRet = space( 7 ) && will return "" if wrong # of days
- do case
- * Days SMTWHFS && if the char in cRet below the dow
- * Dows 1234567 && is blank, can't be Rosh Hashanah
- case m->nDays = 353
- m->cRet = " A B"
- case m->nDays = 354
- m->cRet = " C D "
- case m->nDays = 355
- m->cRet = " E F G"
- case m->nDays = 383
- m->cRet = " H I J"
- case m->nDays = 384
- m->cRet = " K "
- case m->nDays = 385
- m->cRet = " L M N"
- endcase
-
- RETURN trim( substr( m->cRet, dow( m->dR1 ), 1 ) )
- *-- EoF: Kebiah()
-
- FUNCTION Roshashana
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: Returns date of Rosh Hashanah of a given Hebrew year.
- *-- To find date when Rosh Hashanah occurs in a C.E. year,
- *-- add 3761 to the C.E. Year. This formidable-looking
- *-- procedure is actually a straightforward matter of
- *-- using the date and time of one Molad Tishri, the
- *-- moment of new moon starting a year, and advancing or
- *-- setting back that date and time by the number of days,
- *-- hours and chalokim in each period of 19 years, then by
- *-- the number in each month within the balance of the
- *-- years. Since we are concerned only with the molads,
- *-- we need not worry about the number of days in the
- *-- calendar months, but only with the lunar period of 29
- *-- days, 12 hours and 793 chalokim and the number of
- *-- months, giving effect to leap years.
- *-- A chelek, plural chalokim, is 1/1080 of an hour,
- *-- or 3 1/3 seconds, and is traditionally used for these
- *-- calculations, in part because it avoids the need to
- *-- deal with fractions.
- *-- Finally, having determined the civil date of the
- *-- Molad Tishri of the proper year and the hour and
- *-- chalokim within the date, we call a separate function
- *-- to determine the applicability of the dechiyoth or
- *-- postponements that may cause Rosh Hashanah to be
- *-- pushed to a later date.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/26/1993 - Original Version.
- *-- 08/02/1993 - Jay Parsons - nCycles made private.
- *-- Calls.......: NormalH Procedure in DATES.PRG
- *-- Dechiyoth Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Roshashana( <nYear> )
- *-- Example.....: Roshashana( 1993 + 3761 )
- *-- Returns.....: date = civil date of Rosh Hashanah in the year
- *-- Parameters..: nYear = number of year in the Hebrew calendar
- *-----------------------------------------------------------------------
-
- parameters nYear
- private dMoldate, nMolhr, nMolch, nYrs, nMoons, nCycles
-
- * we use the Molad of Tishri 5739, October 2, 1978, as the base
- * for no good reason except it started the most recent cycle.
- m->dMoldate = { 10/02/1978 } && The Hebrew date started 6 p.m.
- m->nMolhr = 11 && Oct. 1, 1978. The molad (new
- m->nMolch = 614 && moon) was 11 614/1080 hrs later
- * adjust for each full 19-year cycle ( machzor koton ), which
- * includes 6939 days, 16 hours and 595 chalokim.
- * if adjusting backward, go to beginning of the cycle in which
- * the specified year falls
- m->nYrs = m->nYear - 5739 && years of difference to adjust.
- m->nCycles = floor( m->nYrs / 19 )
- m->dMoldate = m->dMoldate + 6939 * m->nCycles
- m->nMolhr = m->nMolhr + 16 * m->nCycles
- m->nMolch = m->nMolch + 595 * m->nCycles
- * adjust for leftover months within the cycle; the formula was
- * hacked to return the correct number of months for any number
- * of years from 0 through 19 at the start of a 19-year cycle.
- m->nYrs = m->nYrs - 19 * m->nCycles
- m->nMoons = int( .01 + m->nYrs * 12.374 )
- * one lunar month is 29 days 12 hours 793 chalokim
- m->dMoldate = m->dMoldate + 29 * m->nMoons
- m->nMolhr = m->nMolhr + 12 * m->nMoons
- m->nMolch = m->nMolch + 793 * m->nMoons
- do NormalH with m->dMoldate, m->nMolhr, m->nMolch
-
- RETURN m->dMoldate + Dechiyoth( m->dMolDate, m->nMolhr, m->nMolch )
- *-- EoF: Roshashana()
-
- FUNCTION Dechiyoth
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/26/1993
- *-- Notes.......: Adjusts date of Rosh Hashanah for the four dechiyoth
- *-- ( postponements ) required to regularize the calendar
- *-- and prevent either two days in a row of Sabbath at Yom
- *-- Kippur or Hoshanah Rabbah falling on the Sabbath.
- *-- Days, hours and chalokim are measured from
- *-- 6 p.m. Friday evening, considered the beginning of the
- *-- Sabbath for calendar purposes.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/26/1993
- *-- Calls.......: IsLeapH Function in DATES.PRG
- *-- Called by...: Roshashana(), primarily
- *-- Usage.......: Dechiyoth( <dDate>, <nHrs>, <nChalokim> )
- *-- Example.....: nDay = Dechiyoth( {10/02/1978}, 11, 614 )
- *-- Returns.....: date = civil date of Rosh Hashanah
- *-- Parameters..: dDate = civil date of Molad Tishri
- *-- nHrs = hour of Molad Tishri past 6 pm
- *-- nChalokim = chalokim past the hour of Molad Tishri
- *-----------------------------------------------------------------------
-
- parameters dDate, nHrs, nChalokim
- private nMoldow, nFirst, nNidcheh
-
- m->nMoldow = mod( dow( m->dDate ), 7 )
- m->nNidcheh = 0
- m->nFirst = m->nMoldow
- * 1) if Molad Tishri is after noon, new moon could not be seen
- * anywhere that day, so Rosh Hashanah is pushed off (nidcheh)
- * to the next day--it is to be celebrated on the day the new
- * moon could first be seen.
- if m->nHrs * 1080 + m->nChalokim > 18 * 1080
- m->nNidcheh = 1
- m->nFirst = m->nFirst + 1
- endif
- * 2) if Rosh Hashanah would be Sunday, Wednesday or Friday, it
- * is nidcheh ( again if dechiyah 1 applied ) so that Yom
- * Kippur will not fall on Friday or Sunday creating two days
- * of Sabbath in a row, nor Hoshanah Rabbah fall on Sabbath.
- if m->nFirst = 1 .or. m->nFirst = 4 .or. m->nFirst = 6
- m->nNidcheh = m->nNidcheh + 1
- endif
- * 3) if Molad Tishri in a common year is Tuesday and the next
- * Molad Tishri would be after noon of the Sabbath, this Rosh
- * Hashanah is nidcheh twice so the next Rosh Hashanah will
- * not have to be nidcheh--the result would be that this year
- * would have 356 days, too many.
- if .not. IsLeapH( year( m->dDate ) + 3761 ) .and. m->nMoldow = 3 ;
- .and. 1080 * m->nHrs + m->nChalokim > 9 * 1080 + 204 && 9 hr 204
- m->nNidcheh = 2
- endif
- * 4) if Molad Tishri in a common year following a leap year
- * occurs Monday morning so late that the preceding leap year
- * must have started on Thursday, this Rosh Hashanah is
- * nidcheh so the preceding leap year will not be left with
- * 382 days, too few.
- if IsLeapH( year( m->dDate ) + 3760 ) .and. m->nMoldow = 2 ;
- .and. 1080 * m->nHrs + m->nChalokim > 15 * 1080 + 589 && 15 hr 589
- m->nNidcheh = 1
- endif
-
- RETURN m->nNidcheh
- *-- EoF: Dechiyoth()
-
- FUNCTION IsLeapH
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/27/1993
- *-- Notes.......: Returns .T. or .F. whether a Hebrew year is a leap
- *-- year. The formula is a hack; it returns .T. when the
- *-- position of the year in the cycle is 3, 6, 8, 11, 14,
- *-- 17 or 19 ( the last, because its modulus 19 is 0. )
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/27/1993 -- Original
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: IsLeapH( <nYear> )
- *-- Example.....: ? IsLeapH( 1993 + 3761 )
- *-- Returns.....: logical = true if the year is a leap year, or false
- *-- Parameters..: nYear = number of the year on the Hebrew calendar
- *-----------------------------------------------------------------------
-
- parameters nYear
- private nY
-
- m->nY = mod( m->nYear, 19 )
-
- RETURN mod( m->nY + int( ( m->nY + 3 ) / 11 ), 3 ) = 0
- *-- EoF: IsLeapH()
-
- PROCEDURE NormalH
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/26/1993
- *-- Notes.......: Normalize date and numbers of hours and chalokim
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 03/26/1993 -- Original
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: DO NormalH with <dDate>, <nHrs>, <nChalokim>
- *-- Example.....: DO Normalh with {03/13/1993}, 39, 1452
- *-- Parameters..: dDate = a dBASE civil date
- *-- nHrs = number of hours
- *-- nChalokim = number of chalokim
- *-- Side Effects: This procedure changes its parameters.
- *-----------------------------------------------------------------------
-
- parameters dDate, nHrs, nChalokim
-
- m->nHrs = m->nHrs + floor( m->nChalokim / 1080 )
- m->nChalokim = mod( m->nChalokim, 1080 )
- m->dDate = m->dDate + floor( m->nHrs / 24 )
- m->nHrs = mod( m->nHrs, 24 )
-
- RETURN
- *-- EoP: NormalH
-
- *-----------------------------------------------------------------------
- *-- End of the Jewish Date Routines
- *-----------------------------------------------------------------------
-
- FUNCTION MDY_UDF
- *-----------------------------------------------------------------------
- *-- Programmer..: Angus Scott-Fleming (CIS: 75500,3223)
- *-- Date........: 11/25/1992
- *-- Note........: Print date nicely, regardless of SET CENTURY setting
- *-- : MDY({01/01/80}) prints as "January 01, 80"
- *-- : MDY_UDF({01/01/80}) prints as "January 1, 1980"
- *-- Written for.: dBASE IV 1.5+
- *-- Rev. History: 11/25/1992 -- Original
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: MDY_UDF(<dDate>)
- *-- Example.....: ? MDY_Udf(ctod("01/01/92"))
- *-- Returns.....: character representation of current date
- *-- Parameters..: dDate = date to modify
- *-----------------------------------------------------------------------
-
- parameters dDate
-
- if .not. IsBlank(m->dDate)
- RETURN cmonth(m->dDate)+" "+iif(day(m->dDate)<10,;
- str(day(m->dDate),1),;
- str(day(m->dDate),2))+", "+str(year(m->dDate),4)
- else
- RETURN ""
- endif
- *-- EoF: MDY_UDF()
-
- FUNCTION SWorkDays
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 06/19/1993
- *-- Notes.......: Returns workdays between two dates, excluding the
- *-- first but including the last.
- *-- This function is a shortcut that works only if
- *-- all of the following assumptions are true:
- *-- 1) Workdays are Monday through Friday.
- *-- 2) Holidays are: New Year's Day ( 1/1 )
- *-- Independence Day ( 7/4 )
- *-- Christmas Day ( 12/25 )
- *-- and any selection of floating holidays found
- *-- in the Holiday() function, provided their
- *-- letters are inserted in "cHols" in this
- *-- function. It can be made an additional
- *-- parameter if desired.
- *-- 3) If any holiday falls on Saturday or Sunday,
- *-- it is observed on the closest workday, except
- *-- New Year's Day which is observed on the next
- *-- workday.
- *-- For a more sophisticated treatment of holidays, see
- *-- the functions MakeHols() and WorkDays() in this file.
- *-- Written for.: dBASE IV, 1.1 or higher.
- *-- Rev. History: 06/19/1993 - original function.
- *-- Calls.......: HoliCount() Function in DATES.PRG
- *-- IsLeap() Function in DATES.PRG
- *-- Age2() Function in DATES.PRG
- *-- FDoY() Function in DATES.PRG
- *-- XWorked() Function in DATES.PRG
- *-- WeekDays() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: SWorkDays(<dDate1>,<dDate2>)
- *-- Example.....: SWorkDays(date(),{08/27/94})
- *-- Returns.....: Number of workdays in the period between the dates,
- *-- excluding the first and including the last, or -1
- *-- for error.
- *-- Parameters..: dDate1, dDate2 -- dates limiting the period. etc ...)
- *-----------------------------------------------------------------------
-
- parameters dDate1, dDate2
- private dStart, dEnd, nWork, nYr, cHols
-
- m->cHols = "PMLCT" && codes for five floating holidays
- && President's Day, Memorial Day
- && Labor Day, Columbus Day, Thanksgiving
- * deal with improper arguments
- if type("dDate1") # "D" .or. type("dDate2") # "D"
- RETURN -1
- endif
-
- * and reversal of order
- m->dStart = min( m->dDate1, m->dDate2 )
- m->dEnd = max( m->dDate1, m->dDate2 )
-
- m->nWork = 0
- * Full years contain 52 weeks of 5 workdays each, less all the
- * holidays, plus one day the same day of the week as the
- * starting date of the year, and in leap years one more day.
- * We deal with calendar years and two stub periods to avoid the
- * possibility that a period of one year measured from the
- * starting date may contain more or less than a full year of
- * holidays--a year from January 2 to the next January 2 may
- * contain 0, 1 or 2 Leap Year holidays. 52 * 5 = 260, 260 -
- * 3 holidays always included = 257.
- m->nYr = year( m->dStart ) && start at 1/1 of start year
- do while year( m->dEnd ) > m->nYr
- m->nWork = m->nWork + 257 - len( m->cHols )
- m->nWork = m->nWork + XWorked( iif( IsLeap( m->nYr ), 2, 1 ),;
- dow( ctod( "01/01/" + str( m->nYr, 4 ) ) ) )
- m->nYr = m->nYr + 1
- enddo
-
- * now adjust for the weekdays of the initial year through the
- * start date
- m->nWork = m->nWork ;
- - WeekDays( FDoY( m->dStart ) - 1, m->dStart )
- * and the holidays in that stub period
- m->nWork = m->nWork + HoliCount( m->dStart, m->cHols )
-
- * and for the weekdays of the final partial year
- m->nWork = m->nWork ;
- + WeekDays( FDoy( m->dEnd ) - 1, m->dEnd )
- * and the holidays in that stub period
- m->nWork = m->nWork - HoliCount( m->dEnd, m->cHols )
-
- RETURN m->nWork
- *-- EoF: SWorkDays()
-
- FUNCTION WeekDays
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 06/19/1993
- *-- Notes.......: Returns number of days that are not Saturdays or
- *-- Sundays within a range of dates. Excludes beginning
- *-- date and includes ending date. Range must be less
- *-- than one year. See "SWorkDays()" for method of
- *-- calculating weekdays in a number of full years.
- *-- Does not consider holidays.
- *-- Written for.: dBASE IV, 1.1 or higher.
- *-- Rev. History: 06/19/1993 - original function.
- *-- Calls.......: Age2() Function in DATES.PRG
- *-- XWorked() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: WeekDays(<dDate1>,<dDate2>)
- *-- Example.....: WeekDays( {06/19/93},{12/31/93} )
- *-- Returns.....: Number of weekdays in the period between the dates,
- *-- excluding the first and excluding the last, or -1 for
- *-- error.
- *-- Parameters..: dDate1 -- starting date.
- *-- dDate2 -- ending date.
- *-----------------------------------------------------------------------
-
- parameters dDate1, dDate2
- private dStart, dEnd, nWork
-
- * deal with improper arguments
- if type("dDate1") # "D" .or. type("dDate2") # "D"
- RETURN -1
- endif
-
- * reversal of order
- m->dStart = min( m->dDate1, m->dDate2 )
- m->dEnd = max( m->dDate1, m->dDate2 )
-
- * and periods of a year or more
- if Age2( m->dStart + 1, m->dEnd ) > 0
- RETURN -1
- endif
-
- * 5 days per week for the whole weeks
- m->nWork = 5 * int( ( m->dEnd - m->dStart ) / 7 )
-
- * and the stub days ( revised to accommodate a mod() bug )
- m->nWork = m->nWork ;
- + Xworked( mod( fixed( m->dEnd - m->dStart ), 7 ), ;
- dow( m->dStart + 1 ) )
- RETURN m->nWork
- *-- Eof: WeekDays()
-
- FUNCTION XWorked
- *-----------------------------------------------------------------------
- *-- Programmer..: David Frankenbach (CIS: 72147,2635)
- *-- Date........: 06/20/1993
- *-- Notes.......: Returns number of workdays in a stub period of 0 - 6
- *-- days beginning on the day of the week indicated. Does
- *-- not consider holidays, treats workdays as Monday thru
- *-- Friday.
- *-- Written for.: dBASE IV, 1.1 or higher.
- *-- Rev. History: 06/20/1993 - original function.
- *-- Calls.......: None
- *-- Called by...: None
- *-- Usage.......: XWorked(<nXtra>,<nDow>)
- *-- Example.....: XWorked( 5, 3 )
- *-- Returns.....: Number of workdays in the period, or -1 for error.
- *-- Parameters..: nXtra -- days in the stub period.
- *-- nDoW -- dow() of first day of the stub period.
- *-----------------------------------------------------------------------
-
- parameters nXtra, nDoW
-
- if m->nXtra < 0 .or. m->nXtra > 6 .or. m->nDoW < 1 .or. m->nDoW > 7
- RETURN -1
- endif
-
- if ( m->nDoW = 1 )
- RETURN max( ( m->nXtra - 1 ), 0 )
- else
- RETURN min( m->nXtra, max( 7 - m->nDoW, 0 ) ) ;
- + max( m->nXtra - 9 + m->nDoW, 0 )
- endif
-
- RETURN -1
- *-- EoF: XWorked()
-
- FUNCTION HoliCount
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 06/19/1993
- *-- Notes.......: Returns number of holidays that fall in the portion of
- *-- a calendar year ending with a given date. Always
- *-- includes New Year's Day, transferred if required to
- *-- the 2d or 3d, and July 4 and Xmas, each transferred if
- *-- required to the nearest day not Saturday or Sunday.
- *-- Other holidays are included ( but not transferred ) if
- *-- their codes for the Holiday() function are included in
- *-- the cHols argument.
- *-- Does not include the numbers of Saturdays and Sundays
- *-- in the value returned.
- *-- Written for.: dBASE IV, 1.1 or higher.
- *-- Rev. History: 06/19/1993 - original function.
- *-- Calls.......: Annivrsry() Function in DATES.PRG
- *-- Holiday() Function in DATES.PRG
- *-- FDoY() Function in DATES.PRG
- *-- HolXFer() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Holicount(<dDate>,<cHols>)
- *-- Example.....: Holicount( {06/19/93}, "PMLCT" )
- *-- Returns.....: Number of holidays
- *-- Parameters..: dDate -- date ending the period
- *-- cHols -- list of holidays for function Holiday()
- *-----------------------------------------------------------------------
-
- parameters dDate, cHols
- private dSt, dThis, nH, nHols
-
- m->nH = 1
- m->nHols = 0
- m->dSt = FDoY( m->dDate ) && first day of our year
- do while m->nH < len( m->cHols ) + 4
- do case
- case m->nH <= len( m->cHols ) && a day in cHols
- m->dThis = Holiday( year( m->dSt ), ;
- substr( m->cHols, m->nH, 1 ) )
- case m->nH = len( m->cHols ) && New Year's Day
- m->dThis = HolXFer( m->dSt, "17", "F" )
- case m->nH = len( m->cHols ) + 2 && Independence Day
- m->dThis = ctod( "07/04/" + str( year( m->dDate ), 4 ) )
- m->dThis = HolXFer( m->dThis, "17", "Y" )
- case m->nH = len( m->cHols ) + 3 && Christmas
- m->dThis = ctod( "12/25/" + str( year( m->dDate ), 4 ) )
- m->dThis = HolXFer( m->dThis, "17", "Y" )
- endcase
- if Annivrsry( m->dThis, m->dSt, m->dDate )
- m->nHols = m->nHols + 1
- endif
- m->nH = m->nH + 1
- enddo
-
- RETURN m->nHols
- *-- EoF: Holicount()
-
- FUNCTION HolXfer
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 06/19/1993
- *-- Notes.......: Returns date of celebration of a holiday. This will
- *-- be the date given unless it falls on one of the days
- *-- of the week whose dow() values are given as chars in
- *-- the cDows parameter, in which case it will be
- *-- transferred to the first available date without such
- *-- a dow() either forward, backward or to the nearest
- *-- open date depending on the third cDir parameter being
- *-- "F", "B" or "Y".
- *-- Written for.: dBASE IV, 1.1 or higher.
- *-- Rev. History: 06/19/1993 - original function.
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: HolXfer(<dDate>,<cDows>,<cDir>)
- *-- Example.....: HolXfer( {12/25/93}, "17"," ")
- *-- Returns.....: Date holiday is celebrated
- *-- Parameters..: dDate -- date of the actual holiday.
- *-- cDoWs -- string of all dow() values from which it
- *-- must be transferred if it falls on one.
- *-- cDir -- character "F" for forward transfer only,
- *-- "B" for backward transfer only or "Y" for
- *-- either way, forward being preferred.
- *-------------------------------------------------------------------------------
-
- parameters dDate, cDoWs, cDir
- private nDir, dRet, nMoves
-
- m->dRet = m->dDate
- do case
- case upper( m->cDir ) = "F"
- m->nDir = 1
- case upper( m->cDir ) = "B"
- m->nDir = -1
- case upper( m->cDir ) = "Y"
- m->nDir = 0
- otherwise
- RETURN m->dRet
- endcase
- m->nMoves = 1
- do while str( dow( m->dRet ), 1 ) $ m->cDoWs
- if m->nDir # 0
- m->dRet = m->dRet + m->nDir
- else
- if mod( m->nMoves, 2 ) = 1
- m->dRet = m->dRet + m->nMoves
- else
- m->dRet = m->dRet - m->nMoves
- endif
- m->nMoves = m->nMoves + 1
- endif
- enddo
-
- RETURN m->dRet
- *-- EoF: HolXFer()
-
- *-----------------------------------------------------------------------
- *-- WORKDAYS routines:
- *-- Note to the user: the Makehols.dbf file included is for
- *-- demonstration only, and contains a bizarre set of holidays that
- *-- are surely incorrect for any real organization. Edit it as
- *-- needed for your organization, while retaining the structure.
- *-- See the notes to MakeHols() for the significance of the various
- *-- fields and values allowed therein.
- *-- Jay Parsons (CIS: 72662,1302)
- *-----------------------------------------------------------------------
-
- FUNCTION WorkDays
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/02/1993
- *-- Notes.......: Returns workdays between two dates, excluding the
- *-- first but including the last.
- *-- This function uses a .dbf named "HolsYYYY.dbf",
- *-- with "YYYY" being the four digits of the year, for
- *-- each calendar year of interest. Such a .dbf will be
- *-- created, if possible, if it does not exist by the
- *-- MakeHols() function included elsewhere in this file.
- *-- The .dbf may be created otherwise; the only
- *-- requirements are that its first field must be a date
- *-- and that it be both sorted and ordered on that field
- *-- tag "Holdate". It is suggested that it include a
- *-- second field of character type, length 40, for the
- *-- name of the holiday. The HolsYYYY .dbf must contain
- *-- one record for each non-working day of the year,
- *-- including all Sundays and the like.
- *-- Because this function calls MakeHols() to check
- *-- the timestamp of MakeHols.dbf against that of
- *-- HolsYYYY.dbf, Makehols.dbf must exist even if
- *-- HolsYYYY.dbf is up to date.
- *-- This function may of course be written to use an
- *-- array for the non-working days instead of a .dbf.
- *-- That will require considerably more memory but may
- *-- increase speed of access depending on caching, at the
- *-- price of requiring rebuilding/reloading the array when
- *-- needed.
- *-- Written for.: dBASE IV, 1.1 or higher.
- *-- Rev. History: 06/19/1993 - original function.
- *-- 08/02/1993 - Jay Parsons - cNear and lOk made private.
- *-- Calls.......: MakeHols() Function in DATES.PRG
- *-- IsLeap() Function in DATES.PRG
- *-- DoY() Function in DATES.PRG
- *-- Called by...: None
- *-- Usage.......: WorkDays(<dDate1>,<dDate2>)
- *-- Example.....: WorkDays(date(),{08/27/94})
- *-- Returns.....: Number of workdays in the period between the dates,
- *-- excluding the first and excluding the last, or -1 for
- *-- error.
- *-- Parameters..: dDate1, dDate2 -- dates limiting the period. etc ...)
- *-----------------------------------------------------------------------
-
- parameters dDate1, dDate2
- private dStart, dEnd, nWork, nSt, cHols, cNear, lOk
-
- * deal with improper arguments
- if type("dDate1") # "D" .or. type("dDate2") # "D"
- RETURN -1
- endif
-
- * and reversal of order
- m->dStart = min( m->dDate1, m->dDate2 )
- m->dEnd = max( m->dDate1, m->dDate2 )
-
- m->nWork = 0
- if .not. file( "MAKEHOLS.DBF" )
- RETURN -1
- endif
- m->cNear = set("NEAR")
- set near on
-
- m->nYr = year( m->dStart )
- do while m->nYr <= year( m->dEnd )
- m->lOk = MakeHols( m->nYr )
- if .not. m->lOk
- set near &cNear.
- RETURN -1
- endif
- use "HOLS" + str( m->nYr, 4 ) order HolDate ;
- alias Holsfile in select()
- * Add workdays in whole year, except final year
- if m->nYr # year( m->dEnd )
- m->nWork = m->nWork ;
- + iif( IsLeap( m->nYr ), 366, 365 ) ;
- - reccount( "Holsfile" )
- else
- * for ending year, add earlier days - holidays
- m->nWork = m->nWork + DoY( m->dEnd )
- seek m->dEnd
- m->nWork = m->nWork - iif( eof(), reccount(), ;
- recno() - iif( found(), 0, 1 ) )
- endif
- * For starting year, remove earlier days - holidays
- if m->nYr = year( m->dStart )
- m->nWork = m->nWork - DoY( m->dStart )
- seek m->dStart
- m->nWork = m->nWork + iif( eof(), reccount(), ;
- recno() - iif( found(), 0, 1 ) )
- endif
- m->nYr = m->nYr + 1
- use
- enddo
- set near &cNear.
-
- RETURN m->nWork
- *-- EoF: WorkDays()
-
- FUNCTION MakeHols
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/03/1993
- *-- Notes.......: Makes a .dbf file of name "HolsYYYY.dbf" if the file
- *-- Makehols.dbf is found, where "YYYY" in the name will
- *-- be the four digits of the year. The resulting file
- *-- will contain a record for each non-working day of the
- *-- year and will be sorted in order of date and tagged
- *-- by date tag "HolDate". Returns .T. if successful, or
- *-- .F. If the file "HolsYYYY.dbf" already exists, it
- *-- will be rebuilt only if older than "Makehols.dbf."
- *-- This function uses a .dbf called "Makehols.dbf". If
- *-- it cannot be found, does not exist, the function
- *-- fails. Makehols.dbf may or may not be provided with
- *-- this library. Its structure is:
- *-- HOLTYPE C 1 N Type of holiday
- *-- FIRSTDAY C 6 N date within the year*
- *-- NUMDOW N 1 0 N dow()
- *-- XFER C 1 N Transfer code
- *-- XTEND C 1 N Extendability code
- *-- HOLNAME C 40 N Name of the holiday
- *-- *The FIRSTDAY field is used for other purposes for
- *-- some holiday types. See below
- *-- Values acceptable in the Makehols.dbf fields are:
- *-- Holtype: W = weekly holiday, e.g. Sunday
- *-- X = fixed holiday, e.g. Xmas
- *-- F = floating holiday, e.g. Labor Day
- *-- J = Jewish holiday
- *-- E = Easter or day calculated from it
- *-- FirstDay: for W types, ignored
- *-- for X types, the date "MM/DD/"
- *-- for F types, first date on which
- *-- it can occur, "MM/DD/", or the
- *-- letter to pass to the Holidays()
- *-- function if supported in it.
- *-- for J types, the month and day in the
- *-- Hebrew calendar, such as "01/02"
- *-- for the second day of Rosh
- *-- Hashanah. Dates that occur
- *-- twice in the civil year will be
- *-- included twice. The month is
- *-- understood as the month in a
- *-- common year, Nisan being 7. If
- *-- month 6, Adar, is specified, the
- *-- holiday will be that date in
- *-- Second Adar in leap years.
- *-- To specify a date in I Adar of
- *-- a leap year, use month "00".
- *-- for E types, the val() of this field
- *-- will be used as a displacement
- *-- from Easter, such as "-46" for
- *-- Ash Wednesday.
- *-- NumDow: dow() value of the holiday. Needed
- *-- for W types, and for F types if
- *-- Firstday has a nonzero val(), ignored
- *-- for others.
- *-- XFer: "F", "B", "Y" or other, meaning that
- *-- if the holiday falls on a Weekly-type
- *-- non-working day, transfer it:
- *-- F = Forward,
- *-- B = Backward,
- *-- Y = Yes, either way, or
- *-- other = not at all,
- *-- to the nearest working day in that
- *-- direction. If "Y" is specified, a
- *-- transfer date ahead will be preferred
- *-- to one the same number of days back.
- *-- Xtend: Same characters as Xfer, but here they
- *-- indicate whether the holiday is to be
- *-- extended to cover the intervening day
- *-- if it falls one day away from a weekly
- *-- holiday ( example--the Friday after
- *-- Thanksgiving for some schools ). Mark
- *-- Thanksgiving with "F" or "Y" to have
- *-- the Friday treated as a holiday if
- *-- it would otherwise be the only working
- *-- day between the major holiday and the
- *-- weekend.
- *--
- *-- Makehols.dbf must exist and must have its
- *-- holidays entered properly for this function to
- *-- succeed. Since changes in the specification of
- *-- holidays applicable to an organization are rare,
- *-- no "front end" to facilitate changing the .dbf
- *-- is provided.
- *--
- *-- Each HolsYYYY.dbf file created by this function
- *-- will have the following structure:
- *-- Holdate D 8 Y
- *-- Holname C 40 N
- *-- with one record for each nonworking day,
- *-- including each occurrence of the "W" types such
- *-- as Sundays. Temporary files named Holsstru.dbf,
- *-- Holstemp.dbf and Holstemp.mdx are also created
- *-- and later deleted.
- *--
- *-- Written for.: dBASE IV, 1.5 or higher.
- *-- Rev. History: 06/19/1993 - original version.
- *-- 08/03/1993 - Jay Parsons - retained active .dbf,
- *-- conformed to Civildate()
- *-- Calls.......: Time2Sec() Function in TIME.PRG
- *-- EasterDay() Function in DATES.PRG
- *-- Civildate() Function in DATES.PRG
- *-- HolXfer() Function in DATES.PRG
- *-- AddaHol() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: MakeHols(<nYear>)
- *-- Example.....: MakeHols( 1993 )
- *-- Returns.....: .T. if successful, or .F.
- *-- Parameters..: nYear -- the civil year of interest
- *-------------------------------------------------------------------------------
-
- parameters nYear
- private nYr, cAlias, d1, d2, cName, cHoltype
- private cWeekly, lOk, nMo, cTemp, cFirst
-
- * check for existence of main file
- if .not. file( "MakeHols.dbf" )
- RETURN .F.
- endif
-
- * convert year to four digits
- m->nYr = m->nYear
- if m->nYr < 100
- m->nYr = m->nYr + 100 * int( year( date() ) / 100 )
- endif
-
- * save current work area
- m->cAlias = Alias()
-
- * check date and time stamps. Return if up to date or erase
- m->d1 = fdate( "Makehols.dbf" )
- m->cName = "Hols" + str( nYr, 4 )
- if file( m->cName + ".dbf" )
- m->d2 = fdate( m->cName + ".dbf" )
- if m->d2 > m->d1 .or. ;
- ( m->d2 = m->d1 .and. ;
- Time2Sec( ftime( m->cName + ".dbf" ) ) ;
- > Time2Sec( ftime( "Makehols.dbf" ) ) )
- RETURN .T.
- else
- delete file ( cName + ".dbf" )
- endif
- endif
- select select()
- if file( "Holstemp.dbf" )
- use Holstemp order Holdate
- zap
- else
- use Makehols
- copy to Holsstru structure extended
- use Holsstru
- zap
- append blank
- replace FIELD_NAME with "Holdate", ;
- FIELD_TYPE with "D", FIELD_LEN with 8, ;
- FIELD_DEC with 0, FIELD_IDX with "Y"
- append blank
- replace FIELD_NAME with "Holname", ;
- FIELD_TYPE with "C", FIELD_LEN with 40, ;
- FIELD_DEC with 0, FIELD_IDX with "N"
- create HolsTemp from HolsStru
- index on Holdate tag Holdate
- delete file HolsStru.dbf
- endif
-
- *-- now add the holidays to HolsTemp
- select select()
- use Makehols
- *-- MakeHols may be in no order, so start with weekly holidays
- m->d1 = ctod( "01/01/" + str( m->nYr, 4 ) )
- m->cWeekly = ""
- scan for upper( Holtype ) = "W"
- if upper( str( NumDow, 1 ) ) $ m->cWeekly
- loop
- else
- m->cWeekly = m->cWeekly + upper( str( NumDow, 1 ) )
- endif
- m->d2 = m->d1 + mod( NumDow + 7 - dow( m->d1 ), 7 )
- select Holstemp
- m->lOk = .T.
- do while m->lOk
- m->lOk = AddaHol( m->d2, m->nYr, cDow( m->d2 ) )
- m->d2 = m->d2 + 7
- enddo
- select Makehols
- endscan
-
- *-- then the other holidays
- scan for upper( Holtype ) # "W"
- m->cHoltype = upper( Holtype )
- m->cFirst = trim( Firstday ) ;
- + iif( len( trim( Firstday ) ) = 5, "/","" )
- do case
- * fixed holidays - just transfer and add
- case m->cHoltype = "X"
- m->d1 = ctod( m->cFirst + str( m->nYr,4 ) )
- m->d2 = HolXfer( m->d1, m->cWeekly, upper( Xfer ) )
- m->lOk = AddaHol( m->d2, m->nYr, Holname )
- * floating holidays - use Holiday() or its
- * algorithm to find the date, transfer and add
- case m->cHoltype = "F"
- if val( m->cFirst ) = 0
- m->d1 = Holiday( m->nYr, m->cFirst )
- else
- m->d2 = m->d1 + 7 - NumDow
- m->d1 = m->d2 - dow( m->d2 ) + NumDow
- endif
- m->d2 = HolXfer( m->d1, str( NumDow, 1 ), upper( Xfer ) )
- m->lOk = AddaHol( m->d2, m->nYr, Holname )
- * Easter and dates referred to it - call
- * Easterday() to find the date, xfer and add
- case m->cHoltype = "E"
- m->d1 = EasterDay( m->nYr ) + val( m->cFirst )
- m->d2 = HolXfer( m->d1, m->cWeekly, upper( Xfer ) )
- m->lOk = AddaHol( m->d2, m->nYr, Holname )
- * Jewish holidays - convert to civil date,
- * transfer and add. Some dates, although none
- * of the major holidays, may occur twice in a
- * civil year.
- case m->cHoltype = "J"
- m->nMo = val( m->cFirst )
- * first see if dates late in the Hebrew
- * year occurred early this year
- if m->nMo > 2 .or. m->nMo = 0
- m->d2 = Civildate( m->cFirst + str(m->nYr + 3760, 4 ) )
- if year( m->d2 ) # 0
- m->lOk = AddaHol( m->d2, m->nYr, Holname )
- endif
- endif
- * then check to see if dates early in
- * the Hebrew year occurred late this yr
- if m->nMo > 0 .and. m->nMo < 5
- m->d2 = Civildate( m->cFirst + str(m->nYr + 3761, 4 ) )
- if year( m->d2 ) # 0
- m->lOk = AddaHol( m->d2, m->nYr, Holname )
- endif
- endif
- endcase
-
- * add days for extended holidays as needed
- m->lOk = .F.
- if upper( Xtend ) $ "FY" .and. ;
- str( dow( m->d2 + 2 ), 1 ) $ m->cWeekly .and. ;
- .not. str( dow( m->d2 + 1 ), 1 ) $ m->cWeekly
- m->lOk = AddaHol( m->d2 + 1, m->nYr, trim( Holname ) + " ext" )
- endif
- if upper( Xtend ) $ "BY" .and. ;
- str( dow( m->d2 - 2 ), 1 ) $ m->cWeekly .and. ;
- .not. ( m->lOk .or. str( dow( m->d2 - 1 ), 1 ) ;
- $ m->cWeekly )
- m->lOk = AddaHol( m->d2 - 1, m->nYr, trim( Holname ) + " ext" )
- endif
- endscan
- select Holstemp
- copy to ( m->cName ) with production
- use
- erase Holstemp.dbf
- erase Holstemp.mdx
- select Makehols
- use
- if "" # m->cAlias
- select ( m->cAlias )
- endif
-
- RETURN .T.
- *-- EoF: MakeHols()
-
- FUNCTION AddaHol
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 06/26/1993
- *-- Notes.......: Adds a date to Holstemp if in correct year and not
- *-- already included. Requires a file alias Holstemp in
- *-- order Holdate in one work area and a file alias
- *-- Makehols in another, ordinarily current, work area.
- *-- If a holiday is already included, replaces the name.
- *-- This so that if Makehols() has already included the
- *-- Sundays, for example, but Easter or a Jewish holiday
- *-- which is not transferred falls on Sunday, it will be
- *-- included in Makehols.dbf under the (last) name rather
- *-- than by the name of the day of the week. This makes
- *-- it easier to see in HolsYYYY that it has not been
- *-- omitted by mistake.
- *-- Written for.: dBASE IV, 1.1 or higher.
- *-- Rev. History: 06/26/1993 - original function.
- *-- Calls.......: None
- *-- Called by...: Makehols(), usually.
- *-- Usage.......: AddaHol(<dDate>,<nYr>,<cHolname>)
- *-- Example.....: ? AddaHol( {12/25/93}, 1993, "Christmas" )
- *-- Returns.....: .T. if added, or .F. if not added ( duplicate or wrong
- *-- year)
- *-- Parameters..: dDate -- date to add
- *-- nYr -- year in which it must fall, four digits
- *-- cHolname -- name of the holiday
- *-----------------------------------------------------------------------
-
- parameters dDate, nYr, cHolname
- private lReturn
-
- m->lReturn = .F.
- if year( m->dDate ) = m->nYr
- select Holstemp
- seek m->dDate
- if .not. found()
- append blank
- replace Holdate with m->dDate, ;
- Holname with cHolname
- m->lReturn = .T.
- else
- replace Holname with cHolname
- endif
- select Makehols
- endif
-
- RETURN m->lReturn
- *-- EoF: AddaHol()
-
- FUNCTION Holiday
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/03/1993
- *-- Notes.......: Returns the date of a specified "floating" holiday
- *-- (using table below) for current year.
- *-- Name Code
- *-- President's Day P
- *-- Daylight saving time D
- *-- Memorial Day M
- *-- Labor Day L
- *-- Columbus Day C
- *-- resume Standard time S
- *-- Election Day E
- *-- Thanksgiving T
- *-- Advent (1st Sunday) A
- *-- To add additional days, specify the month and
- *-- date the holiday may first possibly occur, MM/DD/, as
- *-- cFirst, and the dow() on which it occurs as nDow.
- *-- This will work only if the holiday occurs on a fixed
- *-- day of the week in a fixed seven-day period.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/01/1991 - original function.
- *-- 11/15/1991 - Ken Mayer - takes a code and year -- I
- *-- basically simplified the use of the function.
- *-- 04/22/1992 - Jay Parsons - added 'D' and 'S' options
- *-- (daylight saving time and return to standard)
- *--`` 08/03/1993 - Jay Parsons - removed change to parameter
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Holiday(<nYear>,"<cCode>")
- *-- Example.....: ? Holiday(92,"P") && date of President's day, 1992
- *-- Returns.....: Date of specified holiday ...
- *-- Parameters..: nYear = Year you need the holiday date for ...
- *-- cCode = one of the codes above for specific holiday
- *-----------------------------------------------------------------------
-
- parameters nYear,cCode
- private cC,cYear,cFirst,nDoW,dReturn,dBaseDate
-
- m->cC = upper( m->cCode )
- m->cYear = ltrim( str( m->nYear ) )
- do case
- case m->cC = "P" && President's day (3rd Mon Feb)
- m->cFirst = "02/15/"
- m->nDoW = 2
- case m->cC = "D" && Daylight time U.S. (1st Sun Apr)
- m->cFirst = "04/01/"
- m->nDoW = 1
- case m->cC = "M" && Memorial day (last Mon May)
- m->cFirst = "05/25/"
- m->nDoW = 2
- case m->cC = "L" && Labor day (1st Mon Sep)
- m->cFirst = "09/01/"
- m->nDoW = 2
- case m->cC = "C" && Columbus Day (2nd Mon Oct)
- m->cFirst = "10/08/"
- m->nDoW = 2
- case m->cC = "S" && Standard Time U.S. (last Sun Oct)
- m->cFirst = "10/25/"
- m->nDoW = 1
- case m->cC = "E" && Election Day (1st Tues Nov, but
- && not Nov 1)
- m->cFirst = "11/02/"
- m->nDoW = 3
- case m->cC = "T" && Thanksgiving (4th Thurs Nov)
- m->cFirst = "11/22/"
- m->nDoW = 5
- case m->cC = "A" && 1st Sunday of Advent (Sunday
- && closest to Nov 30)
- m->cFirst = "11/27/"
- m->nDoW = 1
- otherwise
- RETURN {} && return blank date for error
- endcase
- * start with first day the holiday may occur and use as the base
- * date that one of the possible dates that is a week ahead less
- * the dow() of the holiday--we later add the dow() back.
- m->dBasedate = ctod( m->cFirst + m->cYear) + 7 - m->nDow
- * Back up to the previous Saturday and add the dow().
- m->dReturn = m->dBaseDate - dow( m->dBaseDate ) + m->nDoW
-
- RETURN m->dReturn
- *-- EoF: Holiday()
-
- FUNCTION IsLeap
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 08/03/1993
- *-- Notes.......: Is the year given a Leap Year? Year given must be
- *-- after 1500 C.E.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/08/1991 - Jay Parsons - original function
- *-- 01/13/1992 - Jay Parsons - updated to handle two-digit
- *-- OR four-digit year.
- *-- 08/03/1993 - Jay Parsons - removed change to parameter
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: IsLeap(<nYear>)
- *-- Example.....: IsLeap(91)
- *-- Returns.....: Logical (.t./.f.)
- *-- Parameters..: nYear = Numeric form of year -- last two digits
- *-- (i.e., 91), or all four digits (i.e., 1991)
- *-----------------------------------------------------------------------
-
- parameter nYear
- private nYr, lReturn
-
- *-- deal with two digit year ...
- m->nYr = m->nYear
- if m->nYr < 100
- m->nYr = m->nYr + 100 * int( year( date() ) / 100 )
- endif
-
- m->lReturn = mod( iif( mod( m->nYr, 100 ) = 0, ;
- m->nYr / 100, m->nYr ), 4 ) = 0
-
- RETURN m->lReturn
- *-- EoF: IsLeap()
-
- FUNCTION Num2Dat
- *-----------------------------------------------------------------------
- *-- Programmer..: Raymond S. Leventhal (CIS: 71544,2140)
- *-- Date........: 06/04/1992
- *-- Notes.......: Changes Date format from *numeric* yymmdd to dBASE
- *-- date format. The author uses an AS/400 and downloads
- *-- data, the YYMMDD format is the date format used by the
- *-- AS/400.
- *-- Rev. History: 06/04/1992 -- Original version
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Num2Dat(<nYyMmDd>)
- *-- Example.....: ?Num2Dat(930820)
- *-- Returns.....: Date format value of nYyMmDd (i.e. 08/20/93)
- *-- Parameters..: nYyMmDd = Numeric value YyMmDd to be converted to
- *-- date
- *-----------------------------------------------------------------------
-
- parameters nYyMmDd
-
- RETURN ctod(substr(ltrim(str(m->nYyMmDd)),3,2)+"/"+;
- right(ltrim(str(m->nYyMmDd)),2)+"/"+;
- left(ltrim(str(m->nYyMmDd)),2))
- *-- EOF: Num2Dat()
-
- FUNCTION Epoch
- *-----------------------------------------------------------------------
- *-- Programmer..: Angus Scott-Fleming (75500,3223)
- *-- Date........: 10/15/1993
- *-- Notes.......: Adjusts a date to within 100 years after a given
- *-- Epoch. Set a PUBLIC date memvar called "dEpoch"
- *-- and set it to the year beginning your Epoch, or use
- *-- method 2 to set the Epoch to the century beginning
- *-- with <year>. There are four ways to use Epoch:
- *-- 1. Epoch(<date>[,.T.]) returns .t., fixes date,
- *-- leaves Epoch unchanged
- *-- 2. Epoch(<date>,<year>) returns fixed date, sets
- *-- Epoch to <year>
- *-- 3. Epoch(<date>,<date>) returns fixed date, leaves
- *-- Epoch unchanged.
- *-- 4. Epoch(<date>,.t.,<yr>) Returns .t., fixes date,
- *-- sets Epoch to <year>
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 10/15/1993 -- Original
- *-- Calls.......: AddYears Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Epoch(<date>,<xReturn>[,<nEpoch>])
- *-- Example.....: @.. GET dDate valid required Epoch(dDate)
- *-- dDate = Epoch(dDate,1900)
- *-- Returns.....: logical
- *-- Parameters..: dDate = date being adjusted
- *-- xReturn = optional to control type of return & epoch
- *-- if logical, return .T.
- *-- if numeric, use as base year for dEpoch
- *-- if date, use as temporary base for Epoch
- *-- nEpoch = optional if logical return is needed to set
- *-- beginning year for Epoch.
- *-----------------------------------------------------------------------
-
- parameters dDate, xReturn, nEpoch
- private dTemp, dDiff
-
- if type("dEpoch") = "U"
- public dEpoch
- store {01/01/1950} to dEpoch && enter your default choice here
- endif
-
- do case
- case pcount() = 3 .and. type("nEpoch") = "N"
- store ctod("01/01/"+str(m->nEpoch,4,0)) to dEpoch
- case type("xReturn") = "N"
- * set both temporary Epoch AND permanent Epoch
- store ctod("01/01/"+str(m->xReturn,4,0)) to dEpoch
- otherwise
- * leave existing dEpoch alone
- endcase
-
- dTemp = iif(type("xReturn") = "D",m->xReturn,m->dEpoch)
- dDiff = m->dDate - m->dTemp
- do while (m->dDiff < 0 .or. m->dDiff > 36525)
- do case
- case m->dDate < m->dTemp
- dDate = AddYears(m->dDate,100)
- case m->dDate => AddYears(m->dTemp,100)
- dDate = AddYears(m->dDate,-100)
- endcase
- dDiff = m->dDate - m->dTemp
- enddo
-
- RETURN iif(type("xReturn")="L",.t.,m->dDate)
- *-- EoF: Epoch()
-
- *=======================================================================
- *-- The following functions have been included for use with routines
- *-- contained in DATES.PRG, but are from other files in the library.
- *=======================================================================
-
- FUNCTION Time2Sec
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/01/1992
- *-- Notes.......: Convert HH:MM:SS or HH:MM:SS.SS string to seconds.
- *-- Written for.: dBASE IV
- *-- Rev. History: 03/01/1992 -- Original
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Time2Sec("<cTime>")
- *-- Example.....: ?Time2Sec("01:24:15")
- *-- Returns.....: Numeric
- *-- Parameters..: cTime = Time string in format HH:MM:SS or HH:MM:SS.SS
- *-----------------------------------------------------------------------
-
- parameters cTime
- private cTemp, nSecs
-
- m->cTemp = cTime
- m->nSecs = 3600 * val( m->cTemp )
- m->cTemp = substr( m->cTemp, at( ":", m->cTemp ) + 1 )
- m->nSecs = m->nSecs + 60 * val( m->cTemp )
-
- RETURN m->nSecs + val( substr( m->cTemp, at( ":", m->cTemp ) + 1 ) )
- *-- EoF: Time2Sec()
-
- FUNCTION Strip
- *----------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 72662,1305)
- *-- Date........: 01/05/1993
- *-- Notes.......: Strips out specified character(s) from a string
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: 01/05/1993 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Strip(<cVar>,<cArg>)
- *-- Example.....: ?strip(dtoc(date(),"/")
- *-- Returns.....: Character
- *-- Parameters..: cVar = variable/field to remove character(s) from
- *-- cArg = item to remove from cVar
- *----------------------------------------------------------------------
-
- parameter cVar, cArg
-
- do while m->cArg $ m->cVar
- cVar = stuff( m->cVar, at( m->cArg, m->cVar ), 1, "" )
- enddo
-
- RETURN m->cVar
- *-- EoF: Strip()
-
- *-----------------------------------------------------------------------
- *-- EoP: DATES.PRG
- *-----------------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-
-